package com.funong.matrix.biz.power.domain;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.funong.matrix.biz.base.dao.SysPermissionDao;
import com.funong.matrix.biz.base.dao.SysRolePermissionDao;
import com.funong.matrix.biz.base.entity.SysPermissionEntity;
import com.funong.matrix.biz.base.entity.SysRolePermissionEntity;
import com.funong.matrix.biz.base.entity.SysRoleUserEntity;
import com.funong.matrix.biz.power.pojo.dto.SysRolePermissionDTO;
import com.funong.matrix.core.dto.QueryDTO;
import com.funong.matrix.core.dto.Result;
import com.funong.matrix.core.enums.IsDeletedEnum;
import com.funong.matrix.core.enums.ResultCodeEnum;
import com.funong.matrix.core.utils.BusinessException;
import com.funong.matrix.core.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysRolePermissionDomainDao {

    @Autowired
    private SysRolePermissionDao sysRolePermissionDao;
    @Autowired
    private SysRoleUserDomainDao sysRoleUserDomainDao;
    @Autowired
    private SysMenuDomainDao menuDomainDao;
    ;
    @Autowired
    private SysRolePermissionDomainDao sysRolePermissionDomainDao;
    @Autowired
    private SysPermissionDao sysPermissionDao;

    public List<String> queryPermissionCodeByRoleCode(String roleCode) {
        List<SysRolePermissionEntity> rolePermissionEntities = sysRolePermissionDao.queryRolePermissionByRoleCode(roleCode);
        return rolePermissionEntities.stream().map(SysRolePermissionEntity::getPermissionCode).collect(Collectors.toList());
    }

    public SysRolePermissionDTO queryPermissionListByRoleCode(String roleCode) {
        SysRolePermissionDTO rolePermissionDTO = new SysRolePermissionDTO();
        List<String> permissionCodeList = queryPermissionCodeByRoleCode(roleCode);
        List<SysRoleUserEntity> roleUserEntities = sysRoleUserDomainDao.queryByRoleCode(roleCode);
        List<Integer> userIdList = roleUserEntities.stream().map(SysRoleUserEntity::hashCode).collect(Collectors.toList());
        List<String> menuCodeList = menuDomainDao.queryMenuCodeByRoleCode(Arrays.asList(roleCode));
        List<SysPermissionEntity> permissionEntities = sysRolePermissionDomainDao.queryPermissionList();
        rolePermissionDTO
                .setRoleCode(roleCode)
                .setPermissionCodeList(permissionCodeList)
                .setUserIdList(userIdList)
                .setMenuCodeList(menuCodeList)
                .setPermissionList(permissionEntities)
        ;

        return rolePermissionDTO;
    }

    public List<String> queryPermissionListByRoleCodeList(List<String> roleCodeList) {
        List<String> permissionCodeList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(roleCodeList)) {
            List<SysRolePermissionEntity> rolePermissionEntities = sysRolePermissionDao.queryPermissionListByRoleCodeList(roleCodeList);
            permissionCodeList = rolePermissionEntities.stream().map(SysRolePermissionEntity::getPermissionCode).distinct().collect(Collectors.toList());
        }
        return permissionCodeList;
    }

    public void saveRolePermission(SysRolePermissionDTO rolePermissionDTO) {
        sysRolePermissionDao.deleteRolePermission(rolePermissionDTO);
        for (String permissionCode : rolePermissionDTO.getPermissionCodeList()) {
            SysRolePermissionEntity sysRolePermissionEntity = new SysRolePermissionEntity();
            sysRolePermissionEntity
                    .setRoleCode(rolePermissionDTO.getRoleCode())
                    .setPermissionCode(permissionCode)
            ;
            sysRolePermissionEntity.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
            sysRolePermissionEntity.setCreatedBy(JwtUtils.getCurrentUserName());
            sysRolePermissionEntity.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
            sysRolePermissionEntity.setUpdatedBy(JwtUtils.getCurrentUserName());
            sysRolePermissionDao.save(sysRolePermissionEntity);
        }
    }

    public void saveRoleUser(SysRolePermissionDTO rolePermissionDTO) {
        sysRoleUserDomainDao.deleteRoleUser(rolePermissionDTO);
        for (Integer userId : rolePermissionDTO.getUserIdList()) {
            SysRoleUserEntity sysRoleUserEntity = new SysRoleUserEntity();
            sysRoleUserEntity
                    .setRoleCode(rolePermissionDTO.getRoleCode())
                    .setUserId(userId)
            ;
            sysRoleUserEntity.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
            sysRoleUserEntity.setCreatedBy(JwtUtils.getCurrentUserName());
            sysRoleUserEntity.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
            sysRoleUserEntity.setUpdatedBy(JwtUtils.getCurrentUserName());
            sysRoleUserDomainDao.save(sysRoleUserEntity);
        }
    }


    public Boolean savePermission(SysPermissionEntity sysPermissionEntity) {
        List<SysPermissionEntity> permissionEntities = sysPermissionDao.queryPermissionByCode(sysPermissionEntity.getCode());
        if (CollectionUtils.isNotEmpty(permissionEntities)) {
            throw new BusinessException(ResultCodeEnum.PERMISSION_CODE_EXISTED);
        }
        if ("0".equalsIgnoreCase(sysPermissionEntity.getParentCode())) {
            sysPermissionEntity.setLevel(1);
        } else {
            SysPermissionEntity parent = sysPermissionDao.getByCode(sysPermissionEntity.getParentCode());
            if (parent == null) {
                throw new BusinessException(ResultCodeEnum.PERMISSION_PARENT_CODE_NOT_EXISTED);
            }
            sysPermissionEntity.setLevel(parent.getLevel() + 1);
        }
        sysPermissionEntity.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));
        sysPermissionEntity.setCreatedBy(JwtUtils.getCurrentUserName());
        sysPermissionEntity.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
        sysPermissionEntity.setUpdatedBy(JwtUtils.getCurrentUserName());
        return sysPermissionDao.save(sysPermissionEntity);
    }

    public Boolean deletePermission(SysPermissionEntity sysPermissionEntity) {
        SysPermissionEntity permission = sysPermissionDao.getById(sysPermissionEntity.getId());
        permission.setIsDeleted(IsDeletedEnum.DELETED.getValue());
        permission.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
        permission.setUpdatedBy(JwtUtils.getCurrentUserName());
        return sysPermissionDao.updateById(permission);
    }

    public Boolean updatePermission(SysPermissionEntity sysPermissionEntity) {
        sysPermissionEntity.setUpdatedAt(Timestamp.valueOf(LocalDateTime.now()));
        sysPermissionEntity.setUpdatedBy(JwtUtils.getCurrentUserName());
        return sysPermissionDao.updateById(sysPermissionEntity);
    }

    public Result queryPermissionList(QueryDTO<SysPermissionEntity> permissionQO) {
        Page<SysPermissionEntity> page = new Page<>(permissionQO.getPageNo(), permissionQO.getPageSize());
        SysPermissionEntity sysPermissionEntity = permissionQO.getCondition();
        IPage<SysPermissionEntity> iPage = sysPermissionDao.queryPermissionList(page, sysPermissionEntity);
        return Result.page(iPage, iPage.getRecords());
    }

    public List<SysPermissionEntity> queryPermissionList() {
        List<SysPermissionEntity> permissionEntities = sysPermissionDao.queryAllPermission();
        Map<String, List<SysPermissionEntity>> map = permissionEntities.stream().sorted(Comparator.comparing(SysPermissionEntity::getOrderNum)).collect(Collectors.groupingBy(SysPermissionEntity::getParentCode));
        List<SysPermissionEntity> allPowerVOList = permissionEntities.stream().map(
                i -> {
                    i.setChildren(map.get(i.getCode()));
                    return i;
                }
        ).collect(Collectors.toList());
        List<SysPermissionEntity> list = allPowerVOList.stream().filter(i -> "0".equalsIgnoreCase(i.getParentCode())).collect(Collectors.toList());
        return list;
    }
}